﻿using log4net;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

namespace AxleNo
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        private static readonly ILog log = LogManager.GetLogger("AxleNo");

        private static readonly int CLOSE_APP = 0x0801;

        private const int listenPort = 6666;

        private byte carCount = 0;

        public byte AxleCount { get; set; } = 0;

        public byte CarCount
        {
            get { return carCount; }
            set 
            {
                if (value != carCount)
                {
                    SendMessageToApp("双髻鲨汽车衡称重软件", "Axle," + AxleCount);
                    log.Info($"第{value}车，轴数是{AxleCount}");
                }

                carCount = value;                
            }
        }

        private SerialPort axlePort = new SerialPort();  //继电器串口

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            log.Info("Axle start up.");

            Thread recvUDPDataThread = new Thread(new ThreadStart(RecvUDPData)) { IsBackground = true };
            recvUDPDataThread.Start();

            axlePort.PortName = ConfigurationManager.AppSettings["AxleUart"];
            axlePort.BaudRate = 9600;
            if (ConfigurationManager.AppSettings["AxleMode"] == "UART")
            {
                try
                {
                    axlePort.Open();

                    if (axlePort.IsOpen)
                    {
                        Thread recvRelayPortDataThread = new Thread(new ThreadStart(RecvAxlePortData)) { IsBackground = true };
                        recvRelayPortDataThread.Start();

                        log.Info("Axle uart open：" + axlePort.PortName);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message);
                }
            }

            ComponentDispatcher.ThreadPreprocessMessage += ComponentDispatcher_ThreadPreprocessMessage;
        }

        private void RecvAxlePortData()
        {
            axlePort.DataReceived += (sender, e) =>
            {
                try
                {
                    byte[] RecvDatas = new byte[axlePort.BytesToRead];
                    axlePort.Read(RecvDatas, 0, RecvDatas.Length);
                    //Console.WriteLine(ByteArrayToHexString(RecvDatas));
                    string dataStr = ByteArrayToHexString(RecvDatas);
                    if (dataStr.StartsWith("A5"))
                    {
                        //Thread.Sleep(120);
                        SendMessageToApp("双髻鲨汽车衡称重软件", "Axle," + RecvDatas[2]);
                        log.Info("轴数：" + RecvDatas[2]);
                    }
                    else
                    {
                        log.Info("Uart Data Format Error:" + dataStr);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message);
                }
            };
        }

        private void RecvUDPData()
        {

            UdpClient listener = new UdpClient(listenPort);
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);

            try
            {
                while (true)
                {
                    byte[] bytes = listener.Receive(ref groupEP);
                    AxleCount = bytes[5];
                    CarCount = bytes[4];
                    //log.Debug($"Received broadcast from {groupEP} :" + ByteArrayToHexString(bytes));
                }
            }
            catch (SocketException e)
            {
                log.Debug(e);
            }
            finally
            {
                listener.Close();
            }
        }

        //接收其他APP传来的消息
        private void ComponentDispatcher_ThreadPreprocessMessage(ref MSG msg, ref bool handled)
        {
            if (msg.message == CLOSE_APP)
            {
                log.Info("Axle closed.");
                Thread.Sleep(100);
                Current.Shutdown();
            }
        }

        //给其他APP发送消息
        private void SendMessageToApp(string appName, string msg)
        {
            Process[] procs = Process.GetProcesses();

            foreach (Process p in procs)
            {
                if (p.ProcessName.Equals(appName))
                {
                    // 获取目标进程句柄
                    IntPtr hWnd = p.MainWindowHandle;

                    // 封装消息
                    byte[] sarr = Encoding.Default.GetBytes(msg);
                    int len = sarr.Length;
                    IPCHelper.COPYDATASTRUCT cds;
                    cds.dwData = (IntPtr)0;
                    cds.cbData = len + 1;
                    cds.lpData = msg;

                    // 发送消息
                    IPCHelper.SendMessage(hWnd, IPCHelper.WM_COPYDATA, IntPtr.Zero, ref cds);
                }
            }
        }

        private string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
            return sb.ToString().ToUpper();
        }
    }


}
